﻿using System.Text;
using System.Web;
using Yitter.IdGenerator;

namespace GoodAdmin.System;

public class FileService : DbRepository<SysFile>, IFileService, ITransient
{
    private readonly IConfigService _configService;

    public FileService(IConfigService configService)
    {
        _configService = configService;
    }

    /// <inheritdoc/>
    public Task<dynamic> Page(FilePageInput input)
    {
        throw new NotImplementedException();
    }

    /// <inheritdoc/>
    public async Task<(string EnginePath, string RelativeDirPath)> CreateFilePath(string type)
    {
        var saveEngine = await GetSaveEngine();
        var enginePath = GetEnginePath(saveEngine);
        //根据分类设置文件存储细分路径
        var path = GetPathByType(type);
        //根据月份创建下级目录
        path = Path.Combine(path, DateTime.Now.ToString("yyyy-MM"));
        return (enginePath, path);
    }

    /// <inheritdoc/>
    public async Task Delete(BaseIdInput input)
    {
        var file = await GetFirstAsync(it => it.Id == input.Id);
        if (file == null) return;
        var enginePath = file.EnginePath;
        var filePath = Path.Combine(enginePath, file.StoragePath);
        if (File.Exists(file.StoragePath))
        {
            File.Delete(file.StoragePath);
        };        
        await DeleteAsync(file);

    }
    /// <inheritdoc/>
    public async Task<IActionResult> Download(BaseIdInput input)
    {
        var file = await GetFirstAsync(it => it.Id == input.Id);
        if (file == null) return null;
        var fileName = HttpUtility.UrlEncode(file.FileName, Encoding.GetEncoding("UTF-8"));
        var enginePath= file.EnginePath;
        var filePath= Path.Combine(enginePath, file.StoragePath);
        return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream")
        {
            FileDownloadName = fileName+file.Suffix,
        };
    }

    /// <inheritdoc/>
    public async Task<IActionResult> Download(string path,string name)
    {
        if (string.IsNullOrEmpty(path))
        {
            throw Oops.Bah(FileErrorCode.F002);
        }
        var saveEngine = await GetSaveEngine();
        var enginePath = GetEnginePath(saveEngine);
        var filePath= Path.Combine(enginePath, path);        
        // 检查文件路径是否有效
        if (!File.Exists(filePath))
        {
            throw Oops.Bah(FileErrorCode.F003);
        }
        var fileName = string.IsNullOrWhiteSpace(name) ? Path.GetFileName(filePath) : name;
        return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream")
        {
            FileDownloadName = fileName,
        };
    }
    /// <inheritdoc/>
    public async Task<SysFile> UploadFile(IFormFile file,string type)
    {
        if (file == null) throw Oops.Bah(FileErrorCode.F004);
        //检查文件大小
        var fileSizeKb = (long)(file.Length / 1024.0);
        var (saveEnginePath, path) = await CreateFilePath(type);
        var suffix = Path.GetExtension(file.FileName).ToLower(); // 后缀
        //重新生成文件名，以免重复
        string fileName = $"{YitIdHelper.NextId()}{suffix}";
        var saveEngine = await GetSaveEngine();
        string storagePath = saveEngine switch
        {
            _ => await StorageLocal(file, saveEnginePath, path, fileName),
        };
        var newFile = new SysFile()
        {
            Engine = saveEngine,
            EnginePath= saveEnginePath,
            FileName = Path.GetFileNameWithoutExtension(file.FileName),//上传文件的实际文件名
            Suffix = suffix,//后缀
            ObjName = fileName,//重新生成的文件名
            SizeKb = fileSizeKb,
            SizeInfo = ConvertFileSize(fileSizeKb),
            StoragePath = storagePath,//文件存储相对路径
        };       
        return newFile;
    }

    /// <inheritdoc/>
    public async Task UploadFileAndSaveDb(IFormFile file, string type)
    {
        var newFile=await UploadFile(file,type);
        await InsertAsync(newFile);
    }

    /// <inheritdoc/> 
    public async Task BatchUploadFileAndSaveDb(IList<IFormFile> files, string type)
    {
        var newFileList = new List<SysFile>();
        foreach(var file in files)
        {
            newFileList.Add(await UploadFile(file,type));
        }
        await InsertRangeAsync(newFileList);
    }
    /// <summary>
    /// 服务器本地存储
    /// </summary>
    /// <param name="file"></param>
    /// <param name="enginePath"></param>
    /// <param name="dirPath">文件夹相对路径</param>
    /// <param name="fileName"></param>
    /// <returns></returns>
    private static async Task<string> StorageLocal(IFormFile file,string enginePath,string dirPath,string fileName)
    {        
        //文件夹路径
        var realDirPath= Path.Combine(enginePath, dirPath);
        // 创建文件夹
        if (!Directory.Exists(realDirPath))
            Directory.CreateDirectory(realDirPath);
        var filePath = Path.Combine(realDirPath, fileName);
        using var stream = File.Create(filePath);
        await file.CopyToAsync(stream);
        return Path.Combine(dirPath, fileName);
    }

    /// <summary>
    /// 根据分类类型设置文件存储细分路径
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    private static string GetPathByType(string type)
    {
        return type switch
        {
            //头像
            FileConst.Avatar => FileConst.AvatarPath,
            //签名
            FileConst.Signature => FileConst.SignaturePath,
            //文档
            FileConst.Document => FileConst.DocumentPath,
            //数据批量导入
            FileConst.BatchImport => FileConst.BatchImportPath,
            //模板文件
            FileConst.Template => FileConst.TemplatePath,
            //图片
            FileConst.Image => FileConst.ImagePath,
            //其它临时文件
            _ => FileConst.TemporaryPath,
        };
    }

    /// <summary>
    /// 将文件大小转换为MB或者KB
    /// </summary>
    /// <param name="size"></param>
    /// <returns></returns>
    private static string ConvertFileSize(long size)
    {
        string fileSize;
        if (size >>10 >= 1)
        {
            fileSize = $"{size >> 10}MB";
        }
        else
        {
            fileSize = $"{size}KB";
        }
        return fileSize;
    }
    /// <summary>
    /// 根据存储引擎获取文件存储路径
    /// </summary>
    /// <param name="engine"></param>
    /// <returns></returns>
    private static string GetEnginePath(string engine=null)
    {
        return engine switch
        {
            _ => App.WebHostEnvironment.WebRootPath,
        };
    }

    private async Task<string> GetSaveEngine()
    {
        return (await _configService.GetConfigInfo(CategoryConst.SYS_CONFIG, ConfigConst.FILE_SAVE_TYPE))?.ConfigValue;
    }

    /// <summary>
    /// 根据存储引擎获取文件存储路径
    /// </summary>
    /// <param name="engine"></param>
    /// <returns></returns>
    private static string GetEngineUrl(string engine = null)
    {
        return engine switch
        {
            _ => CommonUtils.GetLocalhost(),
        };
    }
}